import socket
import threading
import time
import pickle
import uuid


class serverAddress(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        self.sock.bind(('0.0.0.0', 2501))

    def run(self):
        global address
        global stop
        global i
        i = 0
        global ownId
        global event
        global event1
        while True:
            print('wait for TCP address')
            data, addr = self.sock.recvfrom(1024)
            message = data.decode('utf-8')
            message = message.split('|')
            if message[0] == 'host':
                addStr = message[1].split(',')
                addStr[0] = addStr[0].strip('(')
                addStr[0] = addStr[0].strip("'")
                addStr[1] = addStr[1].strip(')')
                address = (addStr[0], int(addStr[1]))
                break
        event.set()
        event1.wait()
        while not stop:
            i += 1
            for n in range(3):
                now = time.time()
                self.sock.sendto(("%s|" % ownId + "%s|" % now + "%s|" % i).encode('utf-8'), ('255.255.255.255', 2400))
                self.sock.sendto(("%s|" % ownId + "%s|" % now + "%s|" % i).encode('utf-8'), ('255.255.255.255', 2401))
                # print("already send to client")
                # print("%s|" % ownId + "%s|" % now + "%s|" % i)
            time.sleep(10)


global address
global stop
stop = True
global i
global ownId
ownId = -1
global bestAddress
global event
event = threading.Event()
global event1
event1 = threading.Event()
global event2
event2 = threading.Event()


class startTcpConnect(threading.Thread):
    def __init__(self, sock):
        threading.Thread.__init__(self)
        self.sock = sock
        mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
        self.sock.send(('car|' + '%s|' % ownId + '%s|' % mac).encode('utf-8'))

    def run(self):
        global ownId
        global stop
        global bestAddress
        global event1
        global event2
        first = True
        while True:
            try:
                data = self.sock.recv(1024)
                message = data.decode('utf-8')
                message = message.split('|')
                if data:
                    if message[0] == 'you':
                        ownId = int(message[1])
                        print("received own carid:%s" % ownId)
                        time.sleep(8)
                        event1.set()
                        stop = False
                    else:
                        print('now,the best address is getting:%s' % message[1])
                        addStr = message[1].split(',')
                        addStr[0] = addStr[0].strip('(')
                        addStr[0] = addStr[0].strip("'")
                        addStr[1] = addStr[1].strip(')')
                        bestAddress = addStr[0]
                        event2.set()
                    if first:
                        sockAddress = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                        threading.Thread(target=sendBestAddress, args=()).start()
                        first = False
                    else:
                        sockAddress.sendto(bestAddress.encode('utf-8'), ('127.0.0.1', 6666))
                        print("The best is:" + bestAddress)
            except Exception:
                print("服务出现异常，TCP连接已中断")
                sockAddress.sendto('error'.encode('utf-8'), ('127.0.0.1', 6666))
                sockAddress.sendto('error'.encode('utf-8'), ('127.0.0.1', 8888))
                self.sock.close()
                bestAddress = '0.0.0.0'
                stop = True
                time.sleep(15)
                restart()
                break


def sendBestAddress():
    print("wait")
    global event2
    sockBest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sockBest.bind(('127.0.0.1', 8888))
    while True:
        data, addr = sockBest.recvfrom(1024)
        message = data.decode('utf-8')
        print(message)
        message = message.split('|')
        if message[0] == 'project':
            if message[1] == 'need address':
                event2.wait()
                print("yes")
                sockBest.sendto(bestAddress.encode('utf-8'), ('127.0.0.1', 6666))
        else:
            event2.clear()
            break


class sendDelayToServer(threading.Thread):
    def __init__(self, sock):
        threading.Thread.__init__(self)
        self.sock = sock

    def run(self):
        global ownId
        global stop
        global event1
        global k
        k = 0
        event1.wait()
        while not stop:
            try:
                k += 1
                now = time.time()
                self.sock.send(('car|' + '%s|' % now + '%s|' % ownId + '%s|' % k).encode('utf-8'))
                # print("already send to server")
                # print('car|' + '%s|' % now + '%s|' % ownId + '%s|' % k)
                time.sleep(10)
            except Exception:
                break


def tcpConnect(address):
    print("%s:%s" % address)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(address)
    print("start tcp connection")
    thread1 = startTcpConnect(sock)
    thread2 = sendDelayToServer(sock)
    thread1.start()
    thread2.start()


def restart():
    global address
    global stop
    stop = False
    thread = serverAddress()
    thread.start()
    event.wait()
    tcpConnect(address)
    event.clear()


if __name__ == '__main__':
    global address
    thread = serverAddress()
    thread.start()
    event.wait()
    time.sleep(5)
    tcpConnect(address)
    event.clear()
